package com.yimils.core.sys.service;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.yimils.core.common.dto.GetQueryParams;
import com.yimils.core.sys.beanUtils.*;
import com.yimils.core.sys.dto.ReqAddUser;
import com.yimils.core.sys.dto.ReqUpdateUser;
import com.yimils.core.sys.entity.*;
import com.yimils.core.sys.mapper.UserMapper;
import com.yimils.core.sys.utils.PageUtils;
import com.yimils.core.sys.vo.*;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;


@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements UserService {

    @Resource(name = "userRoleService")
    private UserRoleService userRoleService;

    @Resource(name = "deptService")
    private DeptService deptService;

    @Resource(name = "roleService")
    private RoleService roleService;

    @Autowired
    private UserVoBeanUtils userBeanUtil;

    @Resource(name = "userService")
    private UserService userService;

    @Autowired
    private TeamVoBeanUtils teamVoBeanUtils;

    @Autowired
    private HotelVoBeanUtils hotelVoBeanUtils;

    @Autowired
    private PartnerVoBeanUtils partnerVoBeanUtils;

    @Autowired
    private FeederVoBeanUtils feederVoBeanUtils;

    @Autowired
    private PartnerAgentVoBeanUtils partnerAgentVoBeanUtils;

    @Resource(name = "userRppService")
    private UserRppService userRppService;

    @Resource(name = "partnerAgentService")
    private PartnerAgentService partnerAgentService;

    @Autowired
    private PageUtils pageUtils;
    @Transactional
    @Override
    public boolean createUser(ReqAddUser reqParams) {
        UserEntity userEntity;
        if (reqParams.getType().equals(UserRoleService.UR_SYS)) {
            userEntity = createInsideUser(reqParams);
        } else {
            userEntity = createOutsideUser(reqParams);
        }
        if (userEntity != null) {
            if (save(userEntity)) {
                UserRoleEntity userRole = new UserRoleEntity();
                userRole.setUserId(userEntity.getId());
                userRole.setRoleId(reqParams.getRoleId());
                userRole.setHotelName(reqParams.getHotelName());
                userRole.setHotelAddr(reqParams.getHotelAddr());
                userRole.setType(reqParams.getType());
                if (userRoleService.save(userRole)) {
                    for (UserRppEntity userRppEntity : reqParams.getRpp()) {
                        userRppEntity.setUserId(userEntity.getId());
                    }
                    if (reqParams.getType().equals(UserRoleService.UR_OPTSPC)) {
                        for (PartnerAgentEntity partnerAgentEntity : reqParams.getPa()) {
                            partnerAgentEntity.setAgentId(userEntity.getId());
                        }
                        partnerAgentService.saveBatch(reqParams.getPa());
                    }
                    return userRppService.saveBatch(reqParams.getRpp());
                }
            }
        }
        return false;
    }

    private UserEntity createInsideUser(ReqAddUser reqParams) {
        UserEntity userEntity = new UserEntity();
        String salt = new SecureRandomNumberGenerator().nextBytes().toString();
        userEntity.setSalt(salt);
        userEntity.setName(reqParams.getUsername());
        userEntity.setNick(reqParams.getNickname());
        userEntity.setPassword(new SimpleHash("SHA-256", reqParams.getPassword(), userEntity.getSalt(), 88).toHex());
        userEntity.setCreateTime(LocalDateTime.now());
        userEntity.setUpdateTime(LocalDateTime.now());
        userEntity.setActive(1);
        userEntity.setBalance(0L);
        userEntity.setGender(reqParams.getGender());
        UserEntity superiorUser = getUserByInviteCode(reqParams.getInviteCode());
        if (superiorUser != null) {
            userEntity.setSuperiorId(superiorUser.getSuperiorId());
        }
        userEntity.setInviteCode(RandomStringUtils.random(6, UUID.randomUUID().toString().split("-")[4]).toUpperCase());
        return userEntity;
    }

    private UserEntity createOutsideUser(ReqAddUser reqParams) {
        UserEntity userEntity = makeUserCommon(reqParams);

        if (reqParams.getType() > 0 && reqParams.getType() < UserRoleService.UR_HOTEL) {
            return createPartner(userEntity, reqParams);
        } else if (reqParams.getType() >= UserRoleService.UR_HOTEL && reqParams.getType() < UserRoleService.UR_FEEDER) {
            return createHotel(userEntity, reqParams);
        } else if (reqParams.getType() >= UserRoleService.UR_FEEDER && reqParams.getType() < UserRoleService.UR_OPTSPC) {
            return createFeeder(userEntity, reqParams);
        } else {
            return createOptSpc(userEntity, reqParams);
        }
    }

    private UserEntity createOptSpc(UserEntity srcEntity, ReqAddUser reqParams) {

        return srcEntity;
    }

    private UserEntity createPartner(UserEntity srcEntity, ReqAddUser reqParams) {
        srcEntity.setInviteCode(RandomStringUtils.random(6, UUID.randomUUID().toString().split("-")[4]).toUpperCase());
        UserEntity superiorUser = getUserByInviteCode(reqParams.getInviteCode());
        if (superiorUser != null) {
            QueryWrapper<UserRoleEntity> qw = new QueryWrapper<>();
            qw.lambda().eq(UserRoleEntity::getUserId, superiorUser.getId())
                    .eq(UserRoleEntity::getType, UserRoleService.UR_SYS);
            UserRoleEntity userRoleEntity = userRoleService.getOne(qw);
            //查询给定邀请码用户是否为系统角色，如果为系统角色，则将上级ID设为空
            if (userRoleEntity != null) {
                srcEntity.setSuperiorId(null);
            } else {
                srcEntity.setSuperiorId(superiorUser.getId());
            }
        }
        return srcEntity;
    }

    private UserEntity createHotel(UserEntity srcEntity, ReqAddUser reqParams) {
        srcEntity.setSuperiorId(reqParams.getSuperiorId());
        return srcEntity;
    }

    private UserEntity createFeeder(UserEntity srcEntity, ReqAddUser reqParams) {
        srcEntity.setSuperiorId(reqParams.getSuperiorId());
        return srcEntity;
    }

    private UserEntity makeUserCommon(ReqAddUser reqParams) {
        UserEntity userEntity = new UserEntity();
        String salt = new SecureRandomNumberGenerator().nextBytes().toString();
        userEntity.setSalt(salt);
        //手机号作为用户名
        userEntity.setName(reqParams.getMobile());
        userEntity.setNick(reqParams.getNickname());
        //初始密码八个八
        userEntity.setPassword(new SimpleHash("SHA-256", "9b5d491b46f372118f9ad0d4d542067c", userEntity.getSalt(), 88).toHex());
        userEntity.setMobile(reqParams.getMobile());
        userEntity.setCreateTime(LocalDateTime.now());
        userEntity.setUpdateTime(LocalDateTime.now());
        userEntity.setActive(1);
        userEntity.setBalance(0L);
        userEntity.setGender(reqParams.getGender());
        //设置分润
        /*if (userRppService.saveBatch(reqParams.getRpp())) {
            return userEntity;
        }*/
        return userEntity;
    }

    private UserEntity getUserByInviteCode(String inviteCode) {
        QueryWrapper<UserEntity> qw = new QueryWrapper<>();
        qw.lambda().eq(UserEntity::getInviteCode, inviteCode);
        return userService.getOne(qw);
    }

    @Override
    public String getUserSalt(String username) {
        UserEntity userEntity;
        QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(UserEntity::getName, username);
        userEntity = getOne(wrapper);
        if (userEntity == null) {
            throw new AuthenticationException();
        }
        return userEntity.getSalt();
    }


    @Override
    public boolean updateUserPassword(Long userId, String password) {
        UserEntity userEntity = getById(userId);
        String salt = new SecureRandomNumberGenerator().nextBytes().toString();
        userEntity.setSalt(salt);
        userEntity.setPassword(new SimpleHash("SHA-256", password, userEntity.getSalt(), 88).toHex());
        userEntity.setUpdateTime(LocalDateTime.now());
        return saveOrUpdate(userEntity);
    }

    @Override
    public boolean lockUser(Long userId, Integer active) {
        UserEntity userEntity = getById(userId);
        userEntity.setActive(active);
        return saveOrUpdate(userEntity);
    }

    @Override
    public boolean changeDept(Long userId, Long deptId) {
        UserEntity userEntity = getById(userId);
        userEntity.setDeptId(deptId);
        return saveOrUpdate(userEntity);
    }

    @Override
    public List<CustomerUserVo> getCustomerUsers(Long superiorId) {
        return getBaseMapper().getCustomerUsers(superiorId);
    }

    @Override
    public boolean updateUserVo(UserVo userVo) {
        UserEntity userEntity = userService.getById(userVo.getId());
        userEntity.setMobile(userVo.getMobile());
        userEntity.setGender(userVo.getGender());
        userEntity.setNick(userVo.getNick());
        userEntity.setEmail(userVo.getEmail());
        if (saveOrUpdate(userEntity)) {
            QueryWrapper<UserRoleEntity> qw = new QueryWrapper<>();
            qw.lambda().eq(UserRoleEntity::getUserId, userVo.getId());
            UserRoleEntity userRoleEntity = userRoleService.getOne(qw);
            userRoleEntity.setHotelName(userVo.getHotelName());
            userRoleEntity.setHotelAddr(userVo.getHotelAddr());
            return userRoleService.saveOrUpdate(userRoleEntity);
        }
        return false;
    }

    @Transactional
    @Override
    public boolean updateUser(ReqUpdateUser dto) {
        UserEntity userEntity = userService.getById(dto.getId());
        userEntity.setMobile(dto.getMobile());
        userEntity.setNick(dto.getNick());
        userEntity.setGender(dto.getGender());
        userEntity.setEmail(dto.getEmail());
        QueryWrapper<UserRoleEntity> qw = new QueryWrapper<>();
        qw.lambda().eq(UserRoleEntity::getUserId, dto.getId());
        UserRoleEntity userRoleEntity = userRoleService.getOne(qw);
        userRoleEntity.setType(dto.getType());
        userRoleEntity.setHotelName(dto.getHotelName());
        userRoleEntity.setHotelAddr(dto.getHotelAddr());
        if (userRoleService.saveOrUpdate(userRoleEntity)) {
            QueryWrapper<UserRppEntity> qwR = new QueryWrapper<>();
            qwR.lambda().eq(UserRppEntity::getUserId, userEntity.getId());
            userRppService.remove(qwR);//分润项 删除重建
            if (userRppService.saveOrUpdateBatch(dto.getRpp())) {
                if (dto.getPa() != null) {
                    QueryWrapper<PartnerAgentEntity> qwP = new QueryWrapper<>();
                    qwP.lambda().eq(PartnerAgentEntity::getAgentId, userEntity.getId());
                    partnerAgentService.remove(qwP);//专员管理酒店 删除重建
                    partnerAgentService.saveOrUpdateBatch(dto.getPa());
                }
                return saveOrUpdate(userEntity);
            }
        }
        return false;
    }

    @Override
    public IPage<TeamVo> getUserTeam(GetQueryParams queryParams) {
        Page<UserEntity> pageParams = new Page<>(queryParams.getPageNo() == null ? 1 : queryParams.getPageNo(),
                queryParams.getPageSize() == null ? 10 : queryParams.getPageSize());
        LambdaQueryWrapper<UserEntity> qw = new LambdaQueryWrapper<>();
        qw.eq(UserEntity::getSuperiorId, queryParams.getSuperiorId());
        IPage<UserEntity> dUsers = getBaseMapper().getUsers(pageParams, queryParams);

        IPage<TeamVo> dUserVo = teamVoBeanUtils.deepClone(dUsers, "一级合伙人");
        for (TeamVo record : dUserVo.getRecords()) {
            LambdaQueryWrapper<UserEntity> iqw = new LambdaQueryWrapper<>();
            iqw.eq(UserEntity::getSuperiorId, record.getId());
            List<UserEntity> iUsers = list(iqw);
            List<TeamVo> iUserVo = teamVoBeanUtils.cloneRecords(iUsers, "二级合伙人");
            record.setChildren(iUserVo);
        }
        return dUserVo;
    }

    public IPage<UserEntity> getUserEntities(GetQueryParams queryParams) {
        Page<UserEntity> pageParams = new Page<>(queryParams.getPageNo() == null ? 1 : queryParams.getPageNo(),
                queryParams.getPageSize() == null ? 10 : queryParams.getPageSize());
        pageUtils.makePageParams(queryParams, pageParams);

        /*if (queryParams.getSuperiorId() != null) {
            QueryWrapper<UserRoleEntity> qw = new QueryWrapper<>();
            qw.lambda().eq(UserRoleEntity::getUserId, queryParams.getSuperiorId());
            UserRoleEntity userRoleEntity = userRoleService.getOne(qw);
            if (userRoleEntity.getType().equals(UserRoleService.UR_SYS)) {
                queryParams.setSuperiorId(null);
            }
        }

        if (StringUtils.isNotBlank(queryParams.getOrderBy())
                && StringUtils.isNotBlank(queryParams.getOrder())) {
            if (queryParams.getOrder().equalsIgnoreCase("asc")) {
                pageParams.setAsc(queryParams.getOrderBy());
            } else {
                pageParams.setDesc(queryParams.getOrderBy());
            }
        }*/
        return getBaseMapper().getUsers(pageParams, queryParams);
    }

    @Override
    public IPage<UserVo> getUsers(GetQueryParams queryParams) {
        IPage<UserEntity> users = getUserEntities(queryParams);
        return userBeanUtil.deepClone(users);
    }

    @Override
    public IPage<PartnerVo> getPartner(GetQueryParams pageParam) {
        IPage<UserEntity> users = getUserEntities(pageParam);
        return partnerVoBeanUtils.deepClone(users);
    }

    @Override
    public IPage<HotelVo> getUserHotel(GetQueryParams queryParams) {
        IPage<UserEntity> users = getUserEntities(queryParams);
        return hotelVoBeanUtils.deepClone(users);
    }

    @Override
    public IPage<FeederVo> getFeeders(GetQueryParams queryParams) {
        IPage<UserEntity> users = getUserEntities(queryParams);
        return feederVoBeanUtils.deepClone(users);
    }

    @Override
    public IPage<PartnerAgentVo> getAgents(GetQueryParams queryParam) {
        IPage<UserEntity> users = getUserEntities(queryParam);
        return partnerAgentVoBeanUtils.deepClone(users);
    }

}
